
/***
 * @Description: 本文件是用来定义网络数据包的格式，数据类型，数据包的链表内存空间分布的头文件
 * @Author: Liverpool
 * @Date: 2024-03-20 02:06:07
 * @LastEditTime: 2024-03-20 02:06:54
 * @LastEditors: Liverpool
 */
#ifndef PACKET_H
#define PACKET_H

#include "config.h"
#include "list.h"
#include "system.h"
#include "debug.h"
#include "netComman.h"
#include "locker.h"
#include "memory_block.h"

// 宏定义
#define PacketBlock_Insertion_Head 0 // 数据块链表的构建方法——头插法
#define PacketBlock_Insertion_Tail 1 // 数据块链表的构建方法——尾插法

#define Packet_PacketBlkList_Head 0 // 数据包链接数据块链表方法——头插法(新的数据块链表插入在原来数据块链表的前面)
#define Packet_PacketBlkList_Tail 1 // 数据包链接数据块链表方法——尾插法(新的数据块链表插入在原来数据块链表的后面)

#define Packet_Header_NoContinuous 0 // 在数据包前面添加不连续包头
#define Packet_Header_Continuous 1   // 在数据包前面添加连续包头
// 定义数据块结构(相当于每个数据包后面真正存储数据的一个个链表结构体)
typedef struct packet_block
{
    D_ListNode node;                          // 在数据块中构成链表的存储结点
    int size;                                 // 该数据块可以存储的内存空间大小(字节)
    uint8_t *data;                            // 在缓存中存储数据的地址
    uint8_t payload[Packet_PacketBlock_Size]; // 每个数据块配套的缓存数组(存储数据)
} D_PacketBlock;

// 定义数据包结构
typedef struct packet
{
    // 结构相关
    int total_size;    // 总共该数据包有多少容量
    D_List block_list; // 链接数据块的链表
    D_ListNode node;   // 数据包的链表结点(多个数据包构成的链表)
    // 读写控制
    int ref;                   // 数据包的引用计数器
    int pos;                   // 当前访问的数据区位置
    D_PacketBlock *curr_block; // 当前访问的数据块
    uint8_t *block_offset;     // 处在当前数据块中的偏移量
} D_Packet;

// 结构调整部分
net_err_t packet_model_init(void);                                           // 对于整个网络数据包这个模块文件进行初始化
D_Packet *packet_alloc(int size);                                            // 分配固定大小的数据包
void packet_free(D_Packet *packet);                                          // 释放数据包内存空间
net_err_t packet_add_header(D_Packet *packet, int size, int continuousMode); // 在数据包前面添加包头
net_err_t packet_remove_header(D_Packet *packet, int size);                  // 在数据包前移除包头
net_err_t packet_resize(D_Packet *packet, int to_size);                      // 重新调整数据包的内存容量大小
net_err_t packet_join(D_Packet *dest, D_Packet *src);                        // 把两个数据包进行合并
net_err_t packet_set_continuous(D_Packet *packet, int size);                 // 把前面的数据包的尺寸空间调整成连续的
// 数据接口部分
void packet_reset_access(D_Packet *packet);                       // 对数据包的数据读写进行初始化
net_err_t packet_write(D_Packet *packet, uint8_t *src, int size); // 往数据包中写入固定尺寸的数据
net_err_t packet_read(D_Packet *packet, uint8_t *dest, int size); // 往数据包中读取固定尺寸的数据
net_err_t packet_seek(D_Packet *packet, int offset);              // 在数据包中定位pos指针
net_err_t packet_copy(D_Packet *dest, D_Packet *src, int size);   // 进行数据包内容的copy
net_err_t packet_fill(D_Packet *packet, uint8_t value, int size); // 对数据包进行数据的填充
void packet_inc_ref(D_Packet *packet);                            // 增加数据包的引用计数
// 数据校验部分
uint16_t packet_checksum_16(D_Packet *packet, int len, uint32_t pre_sum, int complement); // 对数据包进行16位的校验和计算
// ****************************内联函数*******************************
/***
 * @description: (内联函数)根据数据块链表的上一个节点找到下一个数据块节点
 * @Author: Liverpool
 * @Date: 2024-03-26 02:25:39
 * @return {*} 数据块链表中的下一个数据块节点
 * @param {D_PacketBlock} *block 数据块链表的上一个节点
 */
static inline D_PacketBlock *
packetBlock_list_next(D_PacketBlock *block)
{
    D_ListNode *next = list_node_get_next(&block->node);
    return list_entry(next, D_PacketBlock, node);
}
/***
 * @description: (内联函数)根据数据包中的数据块链表找到第一个数据块节点
 * @Author: Liverpool
 * @Date: 2024-03-31 03:27:26
 * @return {*} 数据块链表中的第一个数据块节点
 * @param {D_Packet} *packet 需要进行查找的数据包
 */
static inline D_PacketBlock *packet_first_packetBlock(D_Packet *packet)
{
    D_ListNode *first = list_get_first(&packet->block_list);
    return list_entry(first, D_PacketBlock, node);
}
/***
 * @description: (内联函数)根据数据包中的数据块链表找到最后一个数据块节点
 * @Author: Liverpool
 * @Date: 2024-03-26 02:25:39
 * @return {*} 数据块链表中的最后一个数据块节点
 * @param {D_Packet} *packet 需要进行查找的数据包
 */
static inline D_PacketBlock *packet_last_packetBlock(D_Packet *packet)
{
    D_ListNode *last = list_get_last(&packet->block_list);
    return list_entry(last, D_PacketBlock, node);
}
/***
 * @description: (内联函数)返回数据包的总存储空间
 * @Author: Liverpool
 * @Date: 2024-03-26 02:25:39
 * @return {*} 数据包的总存储空间
 * @param {D_Packet} *packet 需要进行查找的数据包
 */
static inline int packet_total_size(D_Packet *packet)
{
    return packet->total_size;
}
/***
 * @description: (内联函数)返回数据包的第一个数据块的数据存储区域的地址
 * @Author: Liverpool
 * @Date: 2024-04-16 01:47:08
 * @return {*}  第一个数据块的数据存储区域的地址
 * @param {D_Packet} *packet 需要查询的数据包内存地址
 */
static inline uint8_t *packet_firstBlock_data(D_Packet *packet)
{
    D_PacketBlock *first = packet_first_packetBlock(packet);
    return first ? first->data : (uint8_t *)0;
}
#endif // !PACKET_H